﻿Namespace Shows
	Public Class ShowContainer
		Implements ComponentModel.INotifyPropertyChanged

#Region "Notifiers"
		Public Event PropertyChanged(sender As Object, e As ComponentModel.PropertyChangedEventArgs) Implements ComponentModel.INotifyPropertyChanged.PropertyChanged

		Private Sub RaisePropertyChanged(PropertyName As String)
			RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs(PropertyName))
		End Sub
#End Region

		Private ShowFileStatic As String = "ShowFile"
		''' <summary>
		''' Represents the ShowFile Property.
		''' </summary>
		''' <remarks></remarks>
		Private ShowFileProperty As New Shows.ShowFile()
		''' <summary>
		''' The ShowFile that contains all of the unique information about the show, including Cue lists.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property ShowFile As Shows.ShowFile
			Get
				Return ShowFileProperty
			End Get
			Set(value As Shows.ShowFile)
				ShowFileProperty = value
				RaisePropertyChanged(ShowFileStatic)
			End Set
		End Property

		''' <summary>
		''' The console feed for the current project. This information is NOT saved with the file.
		''' </summary>
		''' <value></value>
		''' <returns></returns>
		''' <remarks></remarks>
		Public Property Console As Console.ConsoleFeed
			Get
				Return ConsoleProperty
			End Get
			Set(value As Console.ConsoleFeed)
				ConsoleProperty = value
				RaisePropertyChanged("Console")
			End Set
		End Property

		''' <summary>
		''' Represents the Console property.
		''' </summary>
		''' <remarks></remarks>
		Private WithEvents ConsoleProperty As New Console.ConsoleFeed()

#Region "Public Functions"

		''' <summary>
		''' Executes the next cue or group of cues.
		''' </summary>
		''' <remarks></remarks>
		<Obsolete("Replaced with functionality in CueList.", True)> Public Sub Go(Optional GoCue As Cues.CueBase = Nothing)
			Try
				ShowFile.CueList.Go(GoCue)
			Catch ex As Exception

			End Try
		End Sub


		''' <summary>
		''' This will fire a specific cue and handle all the follow-up needed based on that cue's after-action.
		''' </summary>
		''' <param name="cue">The cue to start.</param>
		''' <param name="Automatic">Defaults to true. If set to False then it will only fire this cue, even if the after-action is set to Next. This is so that when the master GO routine cycles through each cue to check for 'cued' status, cues don't try to trigger twice.</param>
		''' <param name="IgnoreStatus">Defaults to false. If set to False then the target cue must be in standby mode to be triggered. If set to True then any cue targeted will attempt to start, regardless of status.</param>
		''' <returns></returns>
		''' <remarks></remarks>
		<Obsolete("This function has been moved into the newer CueList class", False)> Private Function CueStart(cue As Cues.CueBase, Optional Automatic As Boolean = True, Optional IgnoreStatus As Boolean = False) As Boolean
			If IgnoreStatus = False AndAlso cue.Status <> Cues.CueStatus.Cued Then
				Return False
			End If

			'If cue.Status = Cues.CueStatus.Cued Then
			cue.Start()
			If cue.TransportAction = Cues.CueActions.Next AndAlso ShowFile.CueListCollection.IndexOf(cue) <> ShowFile.CueListCollection.Count - 1 Then
				Dim tc As Cues.CueBase = ShowFile.CueList.ElementAt(ShowFile.CueListCollection.IndexOf(cue) + 1)
				If tc.Status <> Cues.CueStatus.Active Then
					tc.Status = Cues.CueStatus.Cued
					If Not Automatic Then
						CueStart(tc, False)
					End If
				End If
				Return False
			ElseIf cue.TransportAction = Cues.CueActions.Nothing Then
				Dim view = ShowFile.CueList.GetViewBetween(cue, ShowFile.CueList.Max)
				If view.Count > 1 Then
					If view(1).Status <> Cues.CueStatus.Active Then
						view(1).Status = Cues.CueStatus.Cued
					End If
					Return True
				End If
			ElseIf cue.TransportAction = Cues.CueActions.Pause Then
				Dim view = ShowFile.CueList.GetViewBetween(cue, ShowFile.CueList.Max)
				If view.Count > 1 Then
					view(1).Status = Cues.CueStatus.Cued
					Dim objectList(1) As Object
					objectList(0) = cue.ActionDelay
					objectList(1) = view(1)
					Dim t As New System.Threading.Thread(AddressOf DelayedStart)
					ThreadList.Add(t)
					t.SetApartmentState(System.Threading.ApartmentState.STA)
					t.Start(objectList)
					Return True
				End If
			ElseIf cue.TransportAction = Cues.CueActions.AdvanceAtEnd Then
				Dim view = ShowFile.CueList.GetViewBetween(cue, ShowFile.CueList.Max)
				If view.Count > 1 Then
					If view(0).GetType IsNot GetType(Cues.Transport) AndAlso view(1).Status <> Cues.CueStatus.Active Then
						view(1).Status = Cues.CueStatus.Cued
						AddHandler cue.StartTransportAction, Sub()
																 If view(1).Status = Cues.CueStatus.Cued Then
																	 CueStart(view(1))
																 End If
															 End Sub
					ElseIf view(0).GetType Is GetType(Cues.Transport) Then
						view(1).Status = Cues.CueStatus.Cued
						CueStart(view(1))
					End If
					Return True
				End If
			End If
			'End If
			Return False
		End Function

		''' <summary>
		''' A list that keeps track of each thread created to trigger a new cue.
		''' </summary>
		''' <remarks></remarks>
		<Obsolete("Replaced with functionality in CueList.", True)> Private ThreadList As New List(Of System.Threading.Thread)

		''' <summary>
		''' Used by new threads to delay a set period of time and then fire a new cue.
		''' </summary>
		''' <param name="ObjectList"></param>
		''' <remarks></remarks>
		<Obsolete("Replaced with functionality in CueList.", True)> Private Sub DelayedStart(ObjectList() As Object)
			System.Threading.Thread.Sleep(TimeSpan.FromSeconds(ObjectList(0)).TotalMilliseconds)
			Try
				My.Application.Dispatcher.Invoke(Sub() CueStart(ObjectList(1), False))
				ThreadList.Remove(System.Threading.Thread.CurrentThread)
			Catch
			End Try
		End Sub

		''' <summary>
		''' Clears any threads that are running in order to trigger audio cues later. This is mostly useful when stopping all cues at once.
		''' </summary>
		''' <remarks></remarks>
		<Obsolete("Replaced with functionality in CueList.", True)> Public Sub ClearActiveThreads()
			Try
				For Each t As System.Threading.Thread In ThreadList
					t.Abort()
				Next
				ThreadList.Clear()
			Catch
			End Try
		End Sub

		''' <summary>
		''' Stops all the currently active cues and clears any pending cue threads.
		''' </summary>
		''' <remarks></remarks>
		<Obsolete("Replaced with function in CueList.", True)> Public Async Function StopAllCues(Optional UseFade As Boolean = False) As Task
			If ShowFile.CueList.Count > 0 Then
				StopUsingFade = UseFade
				If Not StopUsingFade Then
					For Each cue As Cues.Audio In ShowFile.CueList.OfType(Of Cues.Audio).Where(Function(c) c.Player IsNot Nothing AndAlso c.Player.IsPlaying)
						cue.Player.Mute()
					Next
				End If
				For Each cue As Cues.CueBase In ShowFile.CueList.Where(Function(c)
																		   If c.GetType Is GetType(Cues.Audio) Then
																			   Return CType(c, Cues.Audio).Player IsNot Nothing AndAlso CType(c, Cues.Audio).Player.IsPlaying
																		   Else
																			   Return c.Status = Cues.CueStatus.Active
																		   End If
																	   End Function)
					'cue.Stop(UseFade)
					Dim t As New System.Threading.Thread(AddressOf StopCueThread)
					Dim p(1) As Object
					p(0) = cue
					p(1) = UseFade
					t.Start(cue)
					ActiveStopThreads += 1
				Next
				ClearActiveThreads()
			End If
			Await Task.Run(Sub()
							   Do Until ActiveStopThreads = 0
								   System.Threading.Thread.Sleep(250)
							   Loop
						   End Sub)
		End Function
		<Obsolete("Replaced with functionality in CueList.", True)> Private StopUsingFade As Boolean = True
		<Obsolete("Replaced with functionality in CueList.", True)> Private ActiveStopThreads As Integer = 0

		''' <summary>
		''' Stop all cues uses this to fire multiple threads off to stop large chunks of cues quickly.
		''' </summary>
		''' <param name="Cue"></param>
		''' <remarks></remarks>
		<Obsolete("Replaced with functionality in CueList.", True)> Private Sub StopCueThread(Cue As Cues.CueBase)
			Cue.Stop(StopUsingFade)
			ActiveStopThreads -= 1
		End Sub

		''' <summary>
		''' Stops a specific cue.
		''' </summary>
		''' <param name="Number">The number of the cue to stop.</param>
		''' <remarks></remarks>
		<Obsolete("Replaced with function in a CueList.", True)> Public Sub StopCueByNumber(sender As Cues.Transport, Number As Double)
			ShowFile.CueList.Where(Function(c) c.Number = Number)(0).Stop()
		End Sub

		''' <summary>
		''' Starts a specific cue, by that cue's number.
		''' </summary>
		''' <param name="Number"></param>
		''' <remarks></remarks>
		<Obsolete("Replaced with function in a CueList.", True)> Public Sub StartCueByNumber(sender As Cues.Transport, Number As Double)
			Try
				If sender.ParentCue <> Nothing AndAlso sender.ParentCue <> "-1" AndAlso sender.ParentCue <> "0" AndAlso sender.ParentCue <> "" Then
					Dim num() As String = (sender.ParentCue & ":" & Number).Split(":")
					Dim cue As Cues.CueBase = Nothing
					For i = 0 To num.Length - 1
						If cue Is Nothing Then
							cue = ShowFile.CueList.FindCueByNumber(num(i))
						ElseIf cue.GetType Is GetType(Cues.Stack) Then
							If i = num.Length - 1 Then
								'CType(cue, Cues.Stack).CueList.StartCueByNumber(CType(cue, Cues.Stack).CueList.CueNumber(num(i)).Number, True, True)
								CType(cue, Cues.Stack).CueList.Go(CType(cue, Cues.Stack).CueList.FindCueByNumber(num(i)), True, True)
								Return
							End If
						Else
							cue.Start()
							Return
						End If
						If cue IsNot Nothing AndAlso i = num.Length - 1 Then
							cue.Start()
							Return
						End If
					Next
				Else
					'ShowFile.CueList.StartCueByNumber(Number)
					ShowFile.CueList.Go(ShowFile.CueList.FindCueByNumber(Number))
					Return
				End If
			Catch ex As Exception

			End Try
			'CueStart(ShowFile.CueList.Where(Function(c) c.Number = Number)(0), False, True)
		End Sub

		<Obsolete("Replaced with function in a CueList.", True)> Public Sub BumpCueStatusByNumber(sender As Cues.Transport, Number As Double)
			Try
				If sender.ParentCue <> Nothing AndAlso sender.ParentCue <> "-1" AndAlso sender.ParentCue <> "0" AndAlso sender.ParentCue <> "" Then
					Dim num() As String = (sender.ParentCue & ":" & Number).Split(":")
					Dim cue As Cues.CueBase = Nothing
					For i = 0 To num.Length - 1
						If cue Is Nothing Then
							cue = ShowFile.CueList.FindCueByNumber(num(i))
						ElseIf cue.GetType Is GetType(Cues.Stack) Then
							cue = CType(cue, Cues.Stack).CueList.FindCueByNumber(num(i))
						Else
							cue.BumpStatus()
						End If
					Next
					If cue IsNot Nothing Then
						cue.BumpStatus()
					End If
				Else
					ShowFile.CueList.FindCueByNumber(Number).BumpStatus()
				End If
			Catch ex As Exception

			End Try
			'ShowFile.CueList.Where(Function(c) c.Number = Number)(0).BumpStatus()
		End Sub

		<Obsolete("Replaced with function in a CueList.", True)> Public Sub AutoPanCueByNumber(sender As Cues.Transport, Number As Double)
			Try
				If sender.ParentCue <> Nothing AndAlso sender.ParentCue <> "-1" AndAlso sender.ParentCue <> "0" AndAlso sender.ParentCue <> "" Then
					Dim num() As String = (sender.ParentCue & ":" & Number).Split(":")
					Dim cue As Cues.CueBase = Nothing
					For i = 0 To num.Length - 1
						If cue Is Nothing Then
							cue = ShowFile.CueList.FindCueByNumber(num(i))
						ElseIf cue.GetType Is GetType(Cues.Stack) Then
							cue = CType(cue, Cues.Stack).CueList.FindCueByNumber(num(i))
						Else
							If cue.GetType Is GetType(Cues.Audio) Then
								CType(cue, Cues.Audio).AutoPan(sender.PanDuration, sender.TargetPan)
								Return
							End If
						End If
					Next
					If cue IsNot Nothing Then
						If cue.GetType Is GetType(Cues.Audio) Then
							CType(cue, Cues.Audio).AutoPan(sender.PanDuration, sender.TargetPan)
							Return
						End If
					End If
				Else
					Dim cue As Cues.Audio = TryCast(ShowFile.CueList.FindCueByNumber(Number), Cues.Audio)
					cue.AutoPan(sender.PanDuration, sender.TargetPan)
					Return
				End If
			Catch ex As Exception

			End Try
		End Sub

		<Obsolete("Replace with function in a CueList.", True)> Public Sub AutoFadeCueByNumber(sender As Cues.Transport, Number As Double)
			Try
				If sender.ParentCue <> Nothing AndAlso sender.ParentCue <> "-1" AndAlso sender.ParentCue <> "0" AndAlso sender.ParentCue <> "" Then
					Dim num() As String = (sender.ParentCue & ":" & Number).Split(":")
					Dim cue As Cues.CueBase = Nothing
					For i = 0 To num.Length - 1
						If cue Is Nothing Then
							cue = ShowFile.CueList.FindCueByNumber(num(i))
						ElseIf cue.GetType Is GetType(Cues.Stack) Then
							cue = CType(cue, Cues.Stack).CueList.FindCueByNumber(num(i))
						Else
							If cue.GetType Is GetType(Cues.Audio) Then
								CType(cue, Cues.Audio).AutoFade(sender.FadeDuration, sender.TargetFade)
								Return
							End If
						End If
					Next
					If cue IsNot Nothing Then
						If cue.GetType Is GetType(Cues.Audio) Then
							CType(cue, Cues.Audio).AutoFade(sender.FadeDuration, sender.TargetFade)
							Return
						End If
					End If
				Else
					Dim cue As Cues.Audio = TryCast(ShowFile.CueList.FindCueByNumber(Number), Cues.Audio)
					cue.AutoFade(sender.FadeDuration, sender.TargetFade)
					Return
				End If
			Catch ex As Exception

			End Try
		End Sub


#End Region

	End Class
End Namespace
